package dao

import (
	"OJCenter/dao/mysql"
	"OJCenter/dao/redis"
	"OJCenter/global"
	"OJCenter/idl"
	"encoding/json"
	"errors"
	"strconv"
	"xorm.io/xorm"
)

const ContestInfoPre = "c:"

type ContestInfo struct {
	mysql *mysql.MysqlDao
	redis *redis.RedisDao
}

func NewContestInfo() (*ContestInfo, error) {
	m, err := mysql.NewMysqlDao()
	if err != nil {
		return nil, err
	}
	r, err := redis.NewRedisDao()
	if err != nil {
		return nil, err
	}
	return &ContestInfo{
		mysql: m,
		redis: r,
	}, nil
}

func (u *ContestInfo) GetContestInfo(cid int64) (*idl.Contest, error) {
	var contest idl.Contest
	PInfoJson, err := u.redis.GetString(ContestInfoPre + strconv.Itoa(int(cid)))
	if err != nil {
		_, err := u.mysql.Orm.Where("cid=?", cid).Get(&contest)
		if err != nil {
			return nil, err
		}

		j, _ := json.Marshal(contest)
		err = u.redis.SetString(ContestInfoPre+strconv.Itoa(int(cid)), string(j), u.redis.TTL)
		if err != nil {
			global.Logger.Errorf("Contest load redis failed,err:%v", err)
		}
		return &contest, nil
	}
	err = json.Unmarshal([]byte(PInfoJson), &contest)
	if err != nil {
		global.Logger.Errorf("GetContestInfo unmarshal failed,err:%v", err)
	}
	return &contest, nil
}

func (u *ContestInfo) DeleteContestInfo(info *idl.Contest) error {
	if info == nil {
		return errors.New("info is nil")
	}
	_, err := u.redis.DelKey(ContestInfoPre + strconv.Itoa(int(info.Cid)))
	if err != nil {
		global.Logger.Errorf("Contest load redis failed,err:%v", err)
	}
	cond := make(map[string]interface{})
	cond["cid"] = info.Cid
	sum, err := u.mysql.DeleteInfos("contest", &cond)
	if err != nil || sum == 0 {
		return errors.New("delete Contest failed")
	}
	return nil
}

func (u *ContestInfo) UpdateContestInfo(info map[string]interface{}) error {
	if info == nil {
		return errors.New("info is nil")
	}
	_, err := u.redis.DelKey(ContestInfoPre + strconv.Itoa(int(info["cid"].(int64))))
	if err != nil {
		global.Logger.Errorf("Contest load redis failed,err:%v", err)
	}
	cond := make(map[string]interface{})
	cond["cid"] = info["cid"].(int64)
	sum, err := u.mysql.UpdateInfos("contest", &info, &cond)
	if err != nil || sum == 0 {
		return errors.New("update Contest failed")
	}
	return nil
}

func (u *ContestInfo) InsertContestInfo(info *idl.Contest) error {
	Contest, err := u.GetContestInfo(info.Cid)
	if err != xorm.ErrNotExist {
		return err
	}
	sum, err := u.mysql.InsertInfos("contest", Contest)
	if err != nil || sum == 0 {
		return err
	}
	return nil
}

func (u *ContestInfo) GetContestList(page int, limit int) (*[]idl.Contest, error) {
	var contests []idl.Contest
	err := u.mysql.Orm.Where("is_visible = ?", true).Limit(limit, (page-1)*limit).Find(&contests)
	if err != nil {
		return nil, err
	}
	return &contests, nil
}

func (u *ContestInfo) SelectContest(info *idl.Contest) (*[]idl.Contest, error) {
	var rets []idl.Contest
	err := u.mysql.Orm.Table("contest").Find(&rets, info)
	if err != nil {
		return nil, err
	}
	return &rets, nil
}

func (u *ContestInfo) GetRankList(pid int64, cid int64) {
	u.mysql.Orm.SQL("select commit_time,")
}
